﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading;
using AspNet.Identity.MongoDB;
using MongoDB.Driver;
using MongoDB.Bson;
namespace AspNet.Identity.MongoDB
{
     /// <summary>
     /// Class that encapsulates a MySQL database connections 
     /// and CRUD operations
     /// </summary>
    public class MongoDbDatabase : IDisposable
    {
        private MongoClient _connection;

        /// Default constructor which uses the "DefaultConnection" connectionString
        /// 
        public MongoDbDatabase()
            : this("DefaultConnection")
        {
        }

        /// <summary>
        /// Constructor which takes the connection string name
        /// </summary>
        /// <param name="connectionStringName"></param>
        public MongoDbDatabase(string connectionStringName)
        {
            string connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
            //_connection = new MySqlConnection(connectionString);
            _connection = MongoDbIdentityInstanceStore.IdentityConnection.Client;
        }

        ///// <summary>
        ///// Executes a non-query MySQL statement
        ///// </summary>
        ///// <param name="commandText">The MySQL query to execute</param>
        ///// <param name="parameters">Optional parameters to pass to the query</param>
        ///// <returns>The count of records affected by the MySQL statement</returns>
        //public int Execute(string commandText, Dictionary<string, object> parameters)
        //{
        //    int result = 0;

        //    if (String.IsNullOrEmpty(commandText))
        //    {
        //        throw new ArgumentException("Command text cannot be null or empty.");
        //    }

        //    try
        //    {
        //        EnsureConnectionOpen();
        //        var command = CreateCommand(commandText, parameters);
        //        result = command.ExecuteNonQuery();
        //    }
        //    finally
        //    {
        //       // _connection.Close();
        //    }

        //    return result;
        //}

        /// <summary>
        /// Executes a MySQL query that returns a single scalar value as the result.
        /// </summary>
        /// <param name="commandText">The MySQL query to execute</param>
        /// <param name="parameters">Optional parameters to pass to the query</param>
        /// <returns></returns>
        //public object QueryValue(string commandText, Dictionary<string, object> parameters)
        //{
        //    object result = null;

        //    if (String.IsNullOrEmpty(commandText))
        //    {
        //        throw new ArgumentException("Command text cannot be null or empty.");
        //    }

        //    try
        //    {
        //        EnsureConnectionOpen();
        //        var command = CreateCommand(commandText, parameters);
        //        result = command.ExecuteScalar();
        //    }
        //    finally
        //    {
        //        EnsureConnectionClosed();
        //    }

        //    return result;
        //}

        /// <summary>
        /// Executes a SQL query that returns a list of rows as the result.
        /// </summary>
        /// <param name="commandText">The MySQL query to execute</param>
        /// <param name="parameters">Parameters to pass to the MySQL query</param>
        /// <returns>A list of a Dictionary of Key, values pairs representing the 
        /// ColumnName and corresponding value</returns>
        //public List<Dictionary<string, string>> Query(string commandText, Dictionary<string, object> parameters)
        //{
        //    List<Dictionary<string, string>> rows = null;
        //    if (String.IsNullOrEmpty(commandText))
        //    {
        //        throw new ArgumentException("Command text cannot be null or empty.");
        //    }

        //    try
        //    {
        //        EnsureConnectionOpen();
        //        var command = CreateCommand(commandText, parameters);
        //        using (MySqlDataReader reader = command.ExecuteReader())
        //        {
        //            rows = new List<Dictionary<string, string>>();
        //            while (reader.Read())
        //            {
        //                var row = new Dictionary<string, string>();
        //                for (var i = 0; i < reader.FieldCount; i++)
        //                {
        //                    var columnName = reader.GetName(i);
        //                    var columnValue = reader.IsDBNull(i) ? null : reader.GetString(i);
        //                    row.Add(columnName, columnValue);
        //                }
        //                rows.Add(row);
        //            }
        //        }
        //    }
        //    finally
        //    {
        //        EnsureConnectionClosed();
        //    }

        //    return rows;
        //}

        /// <summary>
        /// Opens a connection if not open
        /// </summary>
        //private void EnsureConnectionOpen()
        //{
        //    //var retries = 3;
        //    //if (_connection.State == ConnectionState.Open)
        //    //{
        //    //    return;
        //    //}
        //    //else
        //    //{
        //    //    while (retries >= 0 && _connection.State != ConnectionState.Open)
        //    //    {
        //    //        _connection.Open();
        //    //        retries--;
        //    //        Thread.Sleep(30);
        //    //    }
        //    //}
        //    return;
        //}

        /// <summary>
        /// Closes a connection if open
        /// </summary>
        //public void EnsureConnectionClosed()
        //{
        //    //if (_connection.State == ConnectionState.Open)
        //    //{
        //    //    _connection.Close();
        //    //}

        //}

        /// <summary>
        /// Creates a MySQLCommand with the given parameters
        /// </summary>
        /// <param name="commandText">The MySQL query to execute</param>
        /// <param name="parameters">Parameters to pass to the MySQL query</param>
        /// <returns></returns>
        //private MySqlCommand CreateCommand(string commandText, Dictionary<string, object> parameters)
        //{
            
        //    MySqlCommand command = _connection.CreateCommand();
        //    command.CommandText = commandText;
        //    AddParameters(command, parameters);

        //    return command;
        //}

        /// <summary>
        /// Adds the parameters to a MySQL command
        /// </summary>
        /// <param name="commandText">The MySQL query to execute</param>
        /// <param name="parameters">Parameters to pass to the MySQL query</param>
        //private static void AddParameters(MySqlCommand command, Dictionary<string, object> parameters)
        //{
        //    if (parameters == null)
        //    {
        //        return;
        //    }

        //    foreach (var param in parameters)
        //    {
        //        var parameter = command.CreateParameter();
        //        parameter.ParameterName = param.Key;
        //        parameter.Value = param.Value ?? DBNull.Value;
        //        command.Parameters.Add(parameter);
        //    }
        //}

        /// <summary>
        /// Helper method to return query a string value 
        /// </summary>
        /// <param name="commandText">The MySQL query to execute</param>
        /// <param name="parameters">Parameters to pass to the MySQL query</param>
        /// <returns>The string value resulting from the query</returns>
        //public string GetStrValue(string commandText, Dictionary<string, object> parameters)
        //{
        //    string value = QueryValue(commandText, parameters) as string;
        //    return value;


        //}
        /// <summary>
        /// 从collection中获取单个数据
        /// </summary>
        /// <param name="key">数据所属的key</param>
        /// <param name="database">数据所在的数据库</param>
        /// <param name="collection">数据所在的collection</param>
        /// <param name="filter">筛选参数</param>
        /// <returns></returns>
        public string GetSingleVal(string key,string database, string collection, BsonDocument filter)
        {
            string value = null;
            var _database = _connection.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            /*var filter = new BsonDocument(parameters);*/
            var list = _collection.Find(filter).Limit(1).ToList();
            try
            {
                foreach (var data in list)
                {
                    value = data[key].ToString();
                }
            }
            catch (Exception e)
            {
                value = null;
                Console.WriteLine(e);
                //throw;
            }
            
            return value;
        }
        /// <summary>
        /// 插入一个新的document
        /// </summary>
        /// <param name="database">需要插入的数据库</param>
        /// <param name="collection">需要插入的collection</param>
        /// <param name="addContent">document的内容</param>
        /// <returns></returns>
        public int InsertSingleDocument(string database, string collection, BsonDocument addContent)
        {
            int result = 0;
            var _database = _connection.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                _collection.InsertOne(addContent);
                result = 1;
            }
            catch (Exception e)
            {
                //throw;
                Console.WriteLine(e);
                result = 0;
            }
            return result;
        }
        /// <summary>
        /// 更新单个数据
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter">筛选内容</param>
        /// <param name="updateContent">更新内容</param>
        /// <returns></returns>
        public int UpdateSingleVal(string database, string collection, BsonDocument filter, BsonDocument updateContent)
        {
            int result = 0;
            long resultLong = 0;
            var _database = _connection.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            var update = new BsonDocument("$set", updateContent);
            try
            {
                resultLong = _collection.UpdateOne(filter, update).ModifiedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        /// <summary>
        /// 删除单个document
        /// </summary>
        /// <param name="database"></param>
        /// <param name="collection"></param>
        /// <param name="filter">筛选</param>
        /// <returns></returns>
        public int DelSingleDocument(string database, string collection, BsonDocument filter)
        {
            int result = 0;
            long resultLong = 0;
            var _database = _connection.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                resultLong = _collection.DeleteOne(filter).DeletedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }

        public List<Dictionary<string, string>> GetManyValList(string database, string collection, BsonDocument filter)
        {
            List<Dictionary<string, string>> rows = null;
            var _database = _connection.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                using (var cursor = _collection.Find(filter).ToCursor())
                {

                    rows = new List<Dictionary<string, string>>();
                    while (cursor.MoveNext())
                    {
                        foreach (var document in cursor.Current)
                        {
                            var row = new Dictionary<string, string>();
                            foreach (var element in document)
                            {
                                var columnName = element.Name;
                                var columnValue = element.Value.ToString();
                                row.Add(columnName, columnValue);
                            }

                            rows.Add(row);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                 rows = null;
                Console.WriteLine(e);
            }

            return rows;
        }

        public int DelDocuments(string database, string collection, BsonDocument filter)
        {
            int result = 0;
            long resultLong = 0;
            var _database = _connection.GetDatabase(database);
            var _collection = _database.GetCollection<BsonDocument>(collection);
            try
            {
                resultLong = _collection.DeleteMany(filter).DeletedCount;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //throw;
                resultLong = 0;
            }

            result = Convert.ToInt32(resultLong);
            return result;
        }
        public void Dispose()
        {
            if (_connection != null)
            {
                //_connection.Dispose();
                //_connection = null;
            }
        }
    }
}
